package com.yoyo.yoyoplat.util;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class Aes {
	
	static final String algorithmStr = "AES/ECB/PKCS5Padding";

	private static final Object TAG = "AES";

	static private KeyGenerator keyGen;

	static private Cipher cipher;

	static boolean isInited = false;

	//注意: 这里的password(秘钥必须是16位的)
	public static final String keyBytes = "qNmLgBx3";

	private static void init() {
	    try {
	        keyGen = KeyGenerator.getInstance("AES");
	    } catch (NoSuchAlgorithmException e) {
	        e.printStackTrace();
	    }
	    // 初始化此密钥生成器，使其具有确定的密钥长度。
	    keyGen.init(128);//128位的AES加密
	    try {
	        // 生成一个实现指定转换的 Cipher 对象。
	        cipher = Cipher.getInstance(algorithmStr);
	    } catch (NoSuchAlgorithmException e) {
	        e.printStackTrace();
	    } catch (NoSuchPaddingException e) {
	        e.printStackTrace();
	    }
	    //标识已经初始化过了的字段
	    isInited = true;
	}

	private static byte[] genKey() {
	    if (!isInited) {
	        init();
	    }
	    //首先 生成一个密钥(SecretKey),
	    //然后,通过这个密钥,返回基本编码格式的密钥，如果此密钥不支持编码，则返回 null。
	    return keyGen.generateKey().getEncoded();
	}

	private static byte[] encrypt(byte[] content, byte[] keyBytes) {
	    byte[] encryptedText = null;
	    if (!isInited) {
	        init();
	    }
	    /**
	     *类 SecretKeySpec
	     *可以使用此类来根据一个字节数组构造一个 SecretKey，
	     *而无须通过一个（基于 provider 的）SecretKeyFactory。
	     *此类仅对能表示为一个字节数组并且没有任何与之相关联的钥参数的原始密钥有用
	     *构造方法根据给定的字节数组构造一个密钥。
	     *此构造方法不检查给定的字节数组是否指定了一个算法的密钥。
	     */
	    Key key = new SecretKeySpec(keyBytes, "AES");
	    try {
	        // 用密钥初始化此 cipher。
	        cipher.init(Cipher.ENCRYPT_MODE, key);
	    } catch (InvalidKeyException e) {
	        e.printStackTrace();
	    }
	    try {
	        // 按单部分操作加密或解密数据，或者结束一个多部分操作。
	        encryptedText = cipher.doFinal(content);
	    } catch (IllegalBlockSizeException e) {
	        e.printStackTrace();
	    } catch (BadPaddingException e) {
	        e.printStackTrace();
	    }
	    return encryptedText;
	}

	private static byte[] encrypt(String content, String password) {
	    try {
	        byte[] keyStr = getKey(password);
	        SecretKeySpec key = new SecretKeySpec(keyStr, "AES");
	        Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr
	        byte[] byteContent = content.getBytes("utf-8");
	        cipher.init(Cipher.ENCRYPT_MODE, key);//   ʼ
	        byte[] result = cipher.doFinal(byteContent);
	        return result;//
	    } catch (NoSuchAlgorithmException e) {
	        e.printStackTrace();
	    } catch (NoSuchPaddingException e) {
	        e.printStackTrace();
	    } catch (InvalidKeyException e) {
	        e.printStackTrace();
	    } catch (UnsupportedEncodingException e) {
	        e.printStackTrace();
	    } catch (IllegalBlockSizeException e) {
	        e.printStackTrace();
	    } catch (BadPaddingException e) {
	        e.printStackTrace();
	    }
	    return null;
	}

	private static byte[] decrypt(byte[] content, String password) {
	    try {
	        byte[] keyStr = getKey(password);
	        SecretKeySpec key = new SecretKeySpec(keyStr, "AES");
	        Cipher cipher = Cipher.getInstance(algorithmStr);//algorithmStr
	        cipher.init(Cipher.DECRYPT_MODE, key);//   ʼ
	        byte[] result = cipher.doFinal(content);
	        return result;//
	    } catch (NoSuchAlgorithmException e) {
	        e.printStackTrace();
	    } catch (NoSuchPaddingException e) {
	        e.printStackTrace();
	    } catch (InvalidKeyException e) {
	        e.printStackTrace();
	    } catch (IllegalBlockSizeException e) {
	        e.printStackTrace();
	    } catch (BadPaddingException e) {
	        e.printStackTrace();
	    }
	    return null;
	}

	private static byte[] getKey(String password) {
	    byte[] rByte = null;
	    if (password != null) {
	        rByte = password.getBytes();
	    } else {
	        rByte = new byte[24];
	    }
	    return rByte;
	}

	/**
	 * 将二进制转换成16进制
	 *
	 * @param buf
	 * @return
	 */
	public static String parseByte2HexStr(byte buf[]) {
	    StringBuffer sb = new StringBuffer();
	    for (int i = 0; i < buf.length; i++) {
	        String hex = Integer.toHexString(buf[i] & 0xFF);
	        if (hex.length() == 1) {
	            hex = '0' + hex;
	        }
	        sb.append(hex.toUpperCase());
	    }
	    return sb.toString();
	}

	/**
	 * 将16进制转换为二进制
	 *
	 * @param hexStr
	 * @return
	 */
	public static byte[] parseHexStr2Byte(String hexStr) {
	    if (hexStr.length() < 1)
	        return null;
	    byte[] result = new byte[hexStr.length() / 2];
	    for (int i = 0; i < hexStr.length() / 2; i++) {
	        int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
	        int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
	                16);
	        result[i] = (byte) (high * 16 + low);
	    }
	    return result;
	}

	/**
	 * 加密
	 * @param content 要加密的内容
	 * @param aesKey 加密所需的密钥 长度为：8位 如：EWERWE23
	 * @return 加密结果返回
	 */
	public static String encode(String content,String aesKey) {
	    // 把字符串aesKey转化成16进制，然后作为 AES密钥Key
	    aesKey =  parseByte2HexStr(aesKey.getBytes());
	    //加密之后的字节数组,转成16进制的字符串形式输出
	    return parseByte2HexStr(encrypt(content, aesKey));
	}

	/**
	 * 解密
	 * @param content 要解密密的内容
	 * @param aesKey 解密所需的密钥 长度为：8位 如：EWERWE23
	 * @return 解密成功后的原文返回
	 */
	public static String decode(String content,String aesKey) {
		String my="";
	    // 把字符串aesKey转化成16进制，然后作为 AES密钥Key
	    aesKey =  parseByte2HexStr(aesKey.getBytes());
	    //解密之前,先将输入的字符串按照16进制转成二进制的字节数组,作为待解密的内容输入
	    byte[] b = decrypt(parseHexStr2Byte(content), aesKey);
	    try {
			my = new String(b, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	    return my;
	}

	/**
	 * 把数组所有元素，按字母排序，然后按照“参数=参数值”的模式用“&”字符拼接成字符串
	 *
	 * @param params
	 *            需要签名的参数
	 * @return 签名的字符串
	 */
	public static String createLinkString(Map<String, Object> params) {
	   List<String> keys =  new ArrayList<String>();
	   Set<String> set=params.keySet();
	   for (String string : set) {
		   keys.add(string);
	   }
	   Collections.sort(keys);
	   StringBuilder signStr = new StringBuilder();
	   for (String key : keys) {
	      if (params.get(key).toString()!=null) {
	    	  signStr.append(key).append("=").append(params.get(key)).append("&");
	      }
	   }
	   return signStr.deleteCharAt(signStr.length() - 1).toString();
	}
	

	
	
}
